import type { IDateTimeHeaderOptions } from '@/app/[locale]/admin/home/date-time-header';
import DateTimeHeader from '@/app/[locale]/admin/home/date-time-header';
import { useEffect, useState } from 'react';
import useToast from '@/hooks/useToast';
import { useQuery } from '@tanstack/react-query';
import {
  queryNginxLogsWebsiteBounceRate,
  queryNginxLogsWebsiteErrorLogLevel,
  queryNginxLogsWebsitePageViews,
  queryNginxLogsWebsiteUniqueVisitors,
} from '@/services/api';
import type {
  INginxLogsWebsiteBounceRate,
  INginxLogsWebsiteErrorLogLevel,
  INginxLogsWebsitePageViews,
  INginxLogsWebsiteUniqueVisitors,
} from '@/interfaces';
import Alert from '@/app/[locale]/alert/alert';
import Spinner from '@/app/[locale]/component/spinner/spinner';
import { calculateDateTimeRange, sumArrayValues } from '@/lib/tool';
import { gsap } from 'gsap';
import dayjs from 'dayjs';
import AlertLoad from '@/app/[locale]/alert/load';
import Nodata from '@/app/[locale]/common/nodata/nodata';
import type { PrefixedTTranslatedFields } from '@/lib/dictionaries';

export default function WebsiteLineDatasets(
  this: any,
  {
    translatedFields,
  }: {
    translatedFields: PrefixedTTranslatedFields<'homeAdminPage'>;
  },
) {
  const [pageViews, setPageViews] = useState(0);
  const [uniqueVisitors, setUniqueVisitors] = useState(0);
  const [bounceRate, setBounceRate] = useState(0);
  const [errorLogLevel, setErrorLogLevel] = useState({
    errorValue: 0,
    warnValue: 0,
  });
  const [params, setParams] = useState({
    ...calculateDateTimeRange(),
  });
  const [options, setOptions] = useState<Partial<IDateTimeHeaderOptions>>({
    activeOptions: {
      custom: false,
      toDay: true,
      yesterday: false,
      d3: false,
      d7: false,
      d15: false,
      d30: false,
    },
    refreshOptions: {
      isLoading: false,
    },
  });
  const { show } = useToast();
  const [details, setDetails] = useState<Record<string, any>>();

  const queryNginxLogsWebsitePageViewsQuery = useQuery(
    ['/nginx', '/logs', '/website', '/page-views', params],
    async (context) => {
      return (await queryNginxLogsWebsitePageViews({
        query: context.queryKey[4] as any,
      })) as INginxLogsWebsitePageViews;
    },
  );
  const queryNginxLogsWebsiteUniqueVisitorsQuery = useQuery(
    ['/nginx', '/logs', '/website', '/unique-visitors', params],
    async (context) => {
      return (await queryNginxLogsWebsiteUniqueVisitors({
        query: context.queryKey[4] as any,
      })) as INginxLogsWebsiteUniqueVisitors;
    },
  );
  const queryNginxLogsWebsiteBounceRateQuery = useQuery(
    ['/nginx', '/logs', '/website', '/bounce-rate', params],
    async (context) => {
      return (await queryNginxLogsWebsiteBounceRate({
        query: context.queryKey[4] as any,
      })) as INginxLogsWebsiteBounceRate;
    },
  );
  const queryNginxLogsWebsiteErrorLogLevelQuery = useQuery(
    ['/nginx', '/logs', '/website', '/error-log-level', params],
    async (context) => {
      return (await queryNginxLogsWebsiteErrorLogLevel({
        query: context.queryKey[4] as any,
      })) as INginxLogsWebsiteErrorLogLevel;
    },
  );

  useEffect(() => {
    if (queryNginxLogsWebsitePageViewsQuery.data) {
      const target = {
        value: 0,
      };
      const value = sumArrayValues(
        Object.values(queryNginxLogsWebsitePageViewsQuery.data.paths),
      );

      gsap.to(target, {
        value,
        duration: 1.5,
        ease: 'power1.inOut',
        onUpdate: () => {
          setPageViews(Math.ceil(target.value));
        },
        onComplete: () => {
          if (!details || Object.keys(details).length === 0) {
            setDetails(queryNginxLogsWebsitePageViewsQuery.data.paths);
          }
        },
      });
    }
  }, [queryNginxLogsWebsitePageViewsQuery.data]);
  useEffect(() => {
    if (queryNginxLogsWebsiteUniqueVisitorsQuery.data) {
      const target = {
        value: 0,
      };
      const value = Object.keys(
        queryNginxLogsWebsiteUniqueVisitorsQuery.data.adders,
      ).length;

      gsap.to(target, {
        value,
        duration: 1.5,
        onUpdate: () => {
          setUniqueVisitors(Math.ceil(target.value));
        },
        ease: 'power1.inOut',
      });
    }
  }, [queryNginxLogsWebsiteUniqueVisitorsQuery.data]);
  useEffect(() => {
    if (queryNginxLogsWebsiteBounceRateQuery.data) {
      const target = {
        value: 0,
      };
      const value = queryNginxLogsWebsiteBounceRateQuery.data.bounceRate;

      gsap.to(target, {
        value,
        duration: 1.5,
        onUpdate: () => {
          setBounceRate(Math.ceil(target.value));
        },
        ease: 'power1.inOut',
      });
    }
  }, [queryNginxLogsWebsiteBounceRateQuery.data]);
  useEffect(() => {
    if (queryNginxLogsWebsiteErrorLogLevelQuery.data) {
      const target = {
        errorValue: 0,
        warnValue: 0,
      };
      const levels = queryNginxLogsWebsiteErrorLogLevelQuery.data.levels;
      const errorValue = levels['error'] ?? 0;
      const warnValue = levels['warn'] ?? 0;

      gsap.to(target, {
        errorValue,
        warnValue,
        duration: 1.5,
        onUpdate: () => {
          setErrorLogLevel({
            errorValue: Math.ceil(target.errorValue),
            warnValue: Math.ceil(target.warnValue),
          });
        },
        ease: 'power1.inOut',
      });
    }
  }, [queryNginxLogsWebsiteErrorLogLevelQuery.data]);

  function onClickPageViews() {
    const data = queryNginxLogsWebsitePageViewsQuery.data;
    if (!data) {
      return;
    }
    setDetails(data.paths);
  }

  function onClickUniqueVisitors() {
    const data = queryNginxLogsWebsiteUniqueVisitorsQuery.data;
    if (!data) {
      return;
    }
    setDetails(data.adders);
  }

  function onClickBounceRate() {
    const data = queryNginxLogsWebsiteBounceRateQuery.data;
    if (!data) {
      return;
    }
    setDetails({
      '/': data.bounceRate + '%',
    });
  }

  function onClickErrorLogLevel(type: string) {
    const data = queryNginxLogsWebsiteErrorLogLevelQuery.data;
    if (!data) {
      return;
    }
    setDetails({
      [type]: data.levels[type] ?? 0,
    });
  }

  function onUpdate(configs: {
    startDateTime: string;
    endDateTime: string;
    activeOptions?: IDateTimeHeaderOptions['activeOptions'];
  }) {
    setParams({
      ...params,
      startDateTime: configs.startDateTime,
      endDateTime: configs.endDateTime,
    });
    setOptions({
      ...options,
      activeOptions: { ...configs.activeOptions },
    });
  }

  function onClickToDay() {
    const { startDateTime, endDateTime } = calculateDateTimeRange();
    onUpdate({
      startDateTime,
      endDateTime,
      activeOptions: {
        toDay: true,
      },
    });
  }

  function onClickYesterday() {
    const { startDateTime, endDateTime } = calculateDateTimeRange(1);
    onUpdate({
      startDateTime,
      endDateTime,
      activeOptions: {
        yesterday: true,
      },
    });
  }

  function onClick3D() {
    const { startDateTime, endDateTime } = calculateDateTimeRange(3);
    onUpdate({
      startDateTime,
      endDateTime,
      activeOptions: {
        d3: true,
      },
    });
  }

  function onClick7D() {
    const { startDateTime, endDateTime } = calculateDateTimeRange(7);
    onUpdate({
      startDateTime,
      endDateTime,
      activeOptions: {
        d7: true,
      },
    });
  }

  function onClick15D() {
    const { startDateTime, endDateTime } = calculateDateTimeRange(15);
    onUpdate({
      startDateTime,
      endDateTime,
      activeOptions: {
        d15: true,
      },
    });
  }

  function onClick30D() {
    const { startDateTime, endDateTime } = calculateDateTimeRange(30);
    onUpdate({
      startDateTime,
      endDateTime,
      activeOptions: {
        d30: true,
      },
    });
  }

  function onClickCustom(startDateValue: string, endDateValue: string) {
    if (!startDateValue || !endDateValue) {
      show({
        type: 'DANGER',
        message: translatedFields.customDateNotSelected,
      });
      return;
    }

    const startDate = dayjs(startDateValue);
    const endDate = dayjs(endDateValue);
    if (endDate.isBefore(startDate)) {
      show({
        type: 'DANGER',
        message: translatedFields.invalidCustomDateFormat,
      });
      return;
    }

    const intervalDays = endDate.diff(startDate, 'day');
    const { startDateTime, endDateTime } = calculateDateTimeRange(intervalDays);
    onUpdate({
      startDateTime,
      endDateTime,
      activeOptions: {
        custom: true,
      },
    });
  }

  async function onClickRefresh() {
    try {
      setOptions({
        ...options,
        refreshOptions: {
          isLoading: true,
        },
      });

      await Promise.all([
        queryNginxLogsWebsitePageViewsQuery.refetch(),
        queryNginxLogsWebsiteUniqueVisitorsQuery.refetch(),
        queryNginxLogsWebsiteBounceRateQuery.refetch(),
        queryNginxLogsWebsiteErrorLogLevelQuery.refetch(),
      ]);

      show({
        type: 'SUCCESS',
        message: '刷新完成',
      });
    } catch (e) {
      show({
        type: 'DANGER',
        message: e,
      });
    } finally {
      setOptions({
        ...options,
        refreshOptions: {
          isLoading: false,
        },
      });
    }
  }

  return (
    <div className="card">
      <div className="card-header bg-transparent">
        <DateTimeHeader
          options={{
            clickOptions: {
              onClickCustom,
              onClickRefresh,
              onClickToDay,
              onClickYesterday,
              onClick3D,
              onClick7D,
              onClick15D,
              onClick30D,
            },
            activeOptions: options.activeOptions!,
            refreshOptions: options.refreshOptions!,
            configs: options.configs!,
          }}
          translatedFields={translatedFields}
        />
      </div>
      <div className="card-body py-4 vstack gap-4">
        <div className="row row-cols-3 g-4 text-center">
          <div className="col-lg-4">
            <div
              onClick={onClickPageViews}
              className="vstack gap-2 cursor-pointer"
            >
              <div className="display-5">
                {queryNginxLogsWebsitePageViewsQuery.data && (
                  <span>{pageViews}</span>
                )}

                {queryNginxLogsWebsitePageViewsQuery.isLoading && (
                  <Spinner sm={false} classs="text-secondary" />
                )}
              </div>
              <div className="">{translatedFields.pageViews}</div>
            </div>

            {queryNginxLogsWebsitePageViewsQuery.isError && (
              <Alert
                message={queryNginxLogsWebsitePageViewsQuery.error}
                type="error"
              />
            )}
          </div>
          <div className="col-lg-4">
            <div
              onClick={onClickUniqueVisitors}
              className="vstack gap-2 cursor-pointer"
            >
              <div className="display-5">
                {queryNginxLogsWebsiteUniqueVisitorsQuery.data && (
                  <span>{uniqueVisitors}</span>
                )}

                {queryNginxLogsWebsiteUniqueVisitorsQuery.isLoading && (
                  <Spinner sm={false} classs="text-secondary" />
                )}
              </div>
              <div className="">{translatedFields.visitors}</div>
            </div>

            {queryNginxLogsWebsiteUniqueVisitorsQuery.isError && (
              <Alert
                message={queryNginxLogsWebsiteUniqueVisitorsQuery.error}
                type="error"
              />
            )}
          </div>
          <div className="col-lg-4">
            <div
              onClick={onClickBounceRate}
              className="vstack gap-2 cursor-pointer"
            >
              <div className="display-5">
                {queryNginxLogsWebsiteBounceRateQuery.data && (
                  <span>{bounceRate}%</span>
                )}

                {queryNginxLogsWebsiteBounceRateQuery.isLoading && (
                  <Spinner sm={false} classs="text-secondary" />
                )}
              </div>
              <div className="">{translatedFields.bounceRate}</div>
            </div>

            {queryNginxLogsWebsiteBounceRateQuery.isError && (
              <Alert
                message={queryNginxLogsWebsiteBounceRateQuery.error}
                type="error"
              />
            )}
          </div>
        </div>
        <div className="row row-cols-2 g-4 text-center">
          <div className="col-lg-6">
            <div
              onClick={onClickErrorLogLevel.bind(this, 'error')}
              className="vstack gap-2 cursor-pointer"
            >
              <div className="display-5">
                {queryNginxLogsWebsiteErrorLogLevelQuery.data && (
                  <span>{errorLogLevel.errorValue}</span>
                )}

                {queryNginxLogsWebsiteErrorLogLevelQuery.isLoading && (
                  <Spinner sm={false} classs="text-secondary" />
                )}
              </div>
              <div className="">{translatedFields.errors}</div>
            </div>

            {queryNginxLogsWebsiteErrorLogLevelQuery.isError && (
              <Alert
                message={queryNginxLogsWebsiteErrorLogLevelQuery.error}
                type="error"
              />
            )}
          </div>
          <div className="col-lg-6">
            <div className="vstack gap-2 cursor-pointer">
              <div
                onClick={onClickErrorLogLevel.bind(this, 'warn')}
                className="display-5"
              >
                {queryNginxLogsWebsiteErrorLogLevelQuery.data && (
                  <span>{errorLogLevel.warnValue}</span>
                )}

                {queryNginxLogsWebsiteErrorLogLevelQuery.isLoading && (
                  <Spinner sm={false} classs="text-secondary" />
                )}
              </div>
              <div className="">{translatedFields.warnings}</div>
            </div>

            {queryNginxLogsWebsiteErrorLogLevelQuery.isError && (
              <Alert
                message={queryNginxLogsWebsiteErrorLogLevelQuery.error}
                type="error"
              />
            )}
          </div>
        </div>

        <div className="row">
          <div className="col-12">
            <hr className="text-secondary opacity-25" />
          </div>
          <div className="col overflow-y-auto" style={{ height: '10.3rem' }}>
            {details ? (
              <>
                {Object.keys(details).length > 0 ? (
                  <ul className="list-group list-group-flush">
                    {Object.keys(details).map((item) => {
                      return (
                        <li
                          key={item}
                          className="list-group-item d-flex justify-content-between align-items-center"
                        >
                          <span>{item}</span>
                          <span className="badge bg-secondary rounded-pill">
                            {details[item]}
                          </span>
                        </li>
                      );
                    })}
                  </ul>
                ) : (
                  <Nodata />
                )}
              </>
            ) : (
              <AlertLoad />
            )}
          </div>
        </div>
      </div>
    </div>
  );
}
